/* eslint-disable */
function getError(action, option, xhr) {
    let msg
    if (xhr.response) {
        msg = `${xhr.response.error || xhr.response}`
    } else if (xhr.responseText) {
        msg = `${xhr.responseText}`
    } else {
        msg = `fail to post ${action} ${xhr.status}`
    }

    const err = new Error(msg)
    err.status = xhr.status
    err.method = 'post'
    err.url = action
    return err
}

function getBody(xhr) {
    const text = xhr.responseText || xhr.response
    if (!text) {
        return text
    }

    try {
        return JSON.parse(text)
    } catch (e) {
        return text
    }
}

function oldUpload(option, onProgress) {
    if (typeof XMLHttpRequest === 'undefined') {
        return
    }

    const xhr = new XMLHttpRequest()
    const action = option.action

    if (xhr.upload) {
        xhr.upload.onprogress = function progress(e) {
            if (e.total > 0) {
                e.percent = e.loaded / e.total * 100
            }
            // option.onProgress(e)
            onProgress(e)
        }
    }

    const formData = new FormData()

    if (option.data) {
        Object.keys(option.data).forEach(key => {
            formData.append(key, option.data[key])
        })
    }

    formData.append(option.filename, option.file, option.file.name)

    xhr.onerror = function error(e) {
        option.onError(e)
    }

    xhr.onload = function onload() {
        if (xhr.status < 200 || xhr.status >= 300) {
            return option.onError(getError(action, option, xhr))
        }

        option.onSuccess(getBody(xhr))
    }

    xhr.open('post', action, true)

    if (option.withCredentials && 'withCredentials' in xhr) {
        xhr.withCredentials = true
    }

    const headers = option.headers || {}

    for (let item in headers) {
        if (headers.hasOwnProperty(item) && headers[item] !== null) {
            xhr.setRequestHeader(item, headers[item])
        }
    }
    xhr.send(formData)
    return xhr
}
// 定义一个函数，用于上传单个分片
export default function upload(option) {
    // 检查分片的接口地址
    var checkUrl = option.checkUrl;
    console.log("自定义分片上传处理逻辑", option);
    // 计算文件的md5
    var fileReader = new FileReader();
    var file = option.file;
    var fileName = file.name;
    // 每一片的大小为2M
    var chunkSize = 2 * 1024 * 1024;
    var chunks = Math.ceil(file.size / chunkSize); // 总片数
    var currentChunk = 0; // 当前片数
    var spark = new SparkMD5.ArrayBuffer();
    // 计算文件的所有md5值
    fileReader.onload = function (e) {
        spark.append(e.target.result);
    };
    var md5 = spark.end();
    fileReader.readAsArrayBuffer(file);
    // 检查文件是否已经上传过，通过接口返回分片索引
    var checkFile = function (uploadFile) {
        var xhr = new XMLHttpRequest();
        xhr.open('POST', checkUrl, true);
        xhr.setRequestHeader('Content-Type', 'application/json');
        // 发送json数据key=value数据
        xhr.send(JSON.stringify({ 
            md5: md5,
            filename: fileName
        }));
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                var res = JSON.parse(xhr.responseText);
                if (res.code === 0) {
                    currentChunk = res.data.chunkIndex;
                }
                uploadFile(currentChunk);
            }
        }
    }
    function uploadChunk(index) {
        return new Promise((resolve, reject) => {
            var start = index * chunkSize;
            var end = start + chunkSize >= file.size ? file.size : start + chunkSize;
            var fileReader = new FileReader();
            var chunk = file.slice(start, end);

            fileReader.onload = function (e) {
                var xhr = new XMLHttpRequest();
                xhr.open('POST', option.action, true);

                // 创建FormData对象
                var formData = new FormData();
                formData.append('md5', md5);
                formData.append('filename', fileName);
                formData.append('chunkIndex', index);
                formData.append('chunkCount', chunks);
                formData.append('file', chunk);

                // 发送FormData对象
                xhr.send(formData);

                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4) {
                        if (xhr.status === 200) {
                            var data = JSON.parse(xhr.responseText);
                            if(data.code === 0) {
                                resolve(index); // 成功上传，将索引传递给resolve
                            } else {
                                reject(xhr.statusText); // 上传失败，将错误信息传递给reject
                            }
                        } else {
                            reject(xhr.statusText); // 上传失败，将错误信息传递给reject
                        }
                    }
                }
            };

            // 读取分片内容
            fileReader.readAsArrayBuffer(chunk);
        });
    }

    // 定义一个函数，用于控制并发上传
    function uploadChunksWithConcurrency(index) {
        // 使用Promise.all来控制并发数不超过3
        var promises = [];
        var endIndex = Math.min(index + 3, chunks); // 控制并发数不超过3
        for (var i = index; i < endIndex; i++) {
            promises.push(uploadChunk(i));
        }

        return Promise.all(promises).then(() => {
            index += 3;
            option.onProgress({
                loaded: index * chunkSize,
                total: file.size,
                percent: index / chunks * 100
            });
            if (index < chunks) {
                return uploadChunksWithConcurrency(index); // 递归调用上传下一批分片
            } else {
                option.onProgress({
                    loaded: file.size,
                    total: file.size,
                    percent: 100
                });
                return Promise.resolve();
            }
        });
    }
    checkFile((index) => {
        uploadChunksWithConcurrency(index).then(() => {
            // 合并文件
            var xhr = new XMLHttpRequest();
            xhr.open('POST', option.mergeUrl, true);
            xhr.setRequestHeader('Content-Type', 'application/json');
            xhr.send(JSON.stringify({ 
                md5: md5,
                filename: fileName,
                chunkCount: chunks
            }));
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    var res = JSON.parse(xhr.responseText);
                    if (res.code === 0) {
                        option.onSuccess();
                    }
                } else {
                    option.onError();
                }
            }
        });
    })
}
